package com.gitee.linzl.zuul.gateway.fiters;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.beans.BeanUtils;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gitee.linzl.zuul.gateway.ZuulRouteExt;
import com.gitee.linzl.zuul.gateway.mapper.ZuulRouteExtMapper;

/**
 * 实现动态路由，可从数据库、缓存、mongodb等获取
 * 
 * @description
 * @author linzl
 * @email 2225010489@qq.com
 * @date 2018年10月23日
 */
public class DBRefreshableRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
	private ZuulProperties properties;
	private ZuulRouteExtMapper mapper;

	public DBRefreshableRouteLocator(String servletPath, ZuulProperties properties, ZuulRouteExtMapper mapper) {
		super(servletPath, properties);
		this.properties = properties;
		this.mapper = mapper;
	}

	@Override
	protected Map<String, ZuulRoute> locateRoutes() {
		Map<String, ZuulRoute> routesMap = new LinkedHashMap<>();
		routesMap.putAll(super.locateRoutes());

		Map<String, ZuulRoute> dbMap = locateRoutesFromDB();
		if (dbMap != null && !dbMap.isEmpty()) {
			routesMap.putAll(dbMap);
		}

		LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
		for (Entry<String, ZuulRoute> entry : routesMap.entrySet()) {
			String path = entry.getKey();
			// Prepend with slash if not already present.
			if (!path.startsWith("/")) {
				path = "/" + path;
			}
			if (StringUtils.hasText(this.properties.getPrefix())) {
				path = this.properties.getPrefix() + path;
				if (!path.startsWith("/")) {
					path = "/" + path;
				}
			}
			values.put(path, entry.getValue());
		}
		return values;
	}

	private Map<String, ZuulRoute> locateRoutesFromDB() {
		QueryWrapper<ZuulRouteExt> query = new QueryWrapper<ZuulRouteExt>();
		// query.lambda().eq(ZuulRouteExt::getEnable, true);
		// query.lambda().eq((zuulRouteExt) -> zuulRouteExt.getEnable(), 1);
		query.eq("enable", 1);
		List<ZuulRouteExt> list = mapper.selectList(query);

		Map<String, ZuulRoute> dbMap = new LinkedHashMap<>();
		if (list != null && list.size() > 0) {
			list.stream()
					.filter(zuulRouteExt -> !StringUtils.isEmpty(zuulRouteExt.getPath())
							&& !StringUtils.isEmpty(zuulRouteExt.getServiceId()))

					.forEach((zuulRouteExt) -> {
						ZuulRoute route = new ZuulRoute();
						BeanUtils.copyProperties(zuulRouteExt, route);
						dbMap.put(route.getPath(), route);
					});
		}
		return dbMap;
	}

	@Override
	public void refresh() {
		doRefresh();
	}
}
